| File: Threading\LazyValue`1.cs | Web Access |
| Project: src\roslyn\src\Razor\src\Shared\Microsoft.AspNetCore.Razor.Utilities.Shared\Microsoft.AspNetCore.Razor.Utilities.Shared.csproj (Microsoft.AspNetCore.Razor.Utilities.Shared) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Runtime.CompilerServices; namespace Microsoft.AspNetCore.Razor.Threading; /// <summary> /// Provides lock-free lazy initialization for a value using a factory function. /// </summary> /// <typeparam name="T">The type of the lazily initialized value.</typeparam> /// <remarks> /// <para> /// <see cref="LazyValue{T}"/> implements a thread-safe lazy initialization pattern that guarantees /// the factory function will be executed exactly once, even when accessed concurrently from multiple threads. /// The implementation uses atomic operations and does not require locks. /// </para> /// <para> /// This struct is designed to be used as a field in classes where expensive initialization should be /// deferred until the value is actually needed. Unlike <see cref="Lazy{T}"/>, this implementation /// does not allocate additional objects and has minimal overhead. /// </para> /// </remarks> /// <example> /// <code> /// private LazyValue<Dictionary<string, int>> _lookup = new(() => BuildExpensiveLookup()); /// /// public Dictionary<string, int> GetLookup() /// { /// return _lookup.GetValue(); // Thread-safe, initialized exactly once /// } /// </code> /// </example> internal struct LazyValue<T> { private readonly Func<T> _factory; private T _value; private int _state; /// <summary> /// Initializes a new instance of the <see cref="LazyValue{T}"/> struct with the specified factory function. /// </summary> /// <param name="factory">A function that creates the value when it is first requested.</param> /// <remarks> /// The factory function will be called at most once, when <see cref="GetValue"/> is first called. /// If multiple threads call <see cref="GetValue"/> concurrently, only one thread will execute /// the factory function, and all threads will receive the same result. /// </remarks> /// <exception cref="ArgumentNullException"><paramref name="factory"/> is <see langword="null"/>.</exception> public LazyValue(Func<T> factory) { _factory = factory; Unsafe.SkipInit(out this); } /// <summary> /// Gets the lazily initialized value, creating it if necessary. /// </summary> /// <returns>The initialized value.</returns> /// <remarks> /// <para> /// This method is thread-safe. If multiple threads call this method concurrently before /// the value has been initialized, the factory function will be executed exactly once, /// and all threads will receive the same result. /// </para> /// <para> /// After the first call, subsequent calls to this method will return the cached value /// without executing the factory function again. /// </para> /// <para> /// The implementation uses <see cref="InterlockedOperations.Initialize{T}(ref T, ref int, Func{T})"/> /// to provide lock-free thread-safe initialization with guaranteed single execution. /// </para> /// </remarks> /// <exception cref="InvalidOperationException"> /// The factory function is <see langword="null"/> (which can only happen if the struct was created using default construction). /// </exception> public T GetValue() => InterlockedOperations.Initialize(ref _value, ref _state, _factory); }